package xyz.bali16.module.chat.controller;


import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.tio.core.Tio;
import xyz.bali16.application.core.model.Result;
import xyz.bali16.application.core.utils.AuthUtils;
import xyz.bali16.application.entity.User;
import xyz.bali16.application.service.UserService;
import xyz.bali16.module.chat.entity.ChatGroup;
import xyz.bali16.module.chat.entity.ChatGroupUser;
import xyz.bali16.module.chat.model.GroupUserVO;
import xyz.bali16.module.chat.service.ChatGroupService;
import xyz.bali16.module.chat.service.ChatGroupUserService;
import xyz.bali16.module.chat.websocket.ImConfigConst;
import xyz.bali16.module.chat.websocket.TioWebsocketStarter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/imChatGroupUser")
public class ChatGroupUserController {

    @Autowired
    private ChatGroupService chatGroupService;

    @Autowired
    private ChatGroupUserService chatGroupUserService;

    @Autowired
    private TioWebsocketStarter tioWebsocketStarter;

    @Autowired
    @AutowiredType(AutowiredType.Type.PLUGIN_MAIN)
    private UserService userService;

    /**
     * 申请加群
     */
    @GetMapping("/enterGroup")
    //@PreAuthorize("@auth.permission('plugin:chat:group:enter')")
    public Result enterGroup(@RequestParam("id") Integer id, @RequestParam(value = "remark", required = false) String remark) {
        ChatGroup chatGroup = chatGroupService.getById(id);
        if (chatGroup == null) {
            return Result.failure("群组不存在！");
        }

        if (chatGroup.getGroupType().intValue() == ImConfigConst.GROUP_TOPIC) {
            return Result.failure("话题无需申请！");
        }

        String username = AuthUtils.getCurrentUsername();
        User currentUser = userService.getByUsername(username);
        String userId = currentUser.getUserId();

        LambdaQueryChainWrapper<ChatGroupUser> lambdaQuery = chatGroupUserService.lambdaQuery();
        lambdaQuery.eq(ChatGroupUser::getGroupId, id);
        lambdaQuery.eq(ChatGroupUser::getUserId, userId);
        ChatGroupUser groupUser = lambdaQuery.one();
        if (groupUser != null) {
            return Result.failure("重复申请！");
        }

        ChatGroupUser chatGroupUser = new ChatGroupUser();
        chatGroupUser.setGroupId(id);
        chatGroupUser.setUserId(userId);
        if (StringUtils.hasText(remark)) {
            chatGroupUser.setRemark(remark);
        }
        if (chatGroup.getJoinType() == ImConfigConst.JOIN_TYPE_TRUE) {
            chatGroupUser.setStatus(ImConfigConst.GROUP_USER_STATUS_NOT_VERIFY);
        } else {
            chatGroupUser.setStatus(ImConfigConst.GROUP_USER_STATUS_PASS);
        }
        boolean isSuccess = chatGroupUserService.save(chatGroupUser);
        if (isSuccess && chatGroup.getJoinType() == ImConfigConst.JOIN_TYPE_FALSE) {
            Tio.bindGroup(tioWebsocketStarter.getServerTioConfig(), String.valueOf(userId), String.valueOf(id));
        }
        return Result.success();
    }

    /**
     * 改变群组用户状态
     * <p>
     * 用户状态[-1:审核不通过或者踢出群组，1:审核通过，2:禁言]
     */
    @GetMapping("/changeUserStatus")
    //@PreAuthorize("@auth.permission('plugin:chat:group:update')")
    public Result changeUserStatus(@RequestParam("groupId") Integer groupId,
                                         @RequestParam("userId") Integer userId,
                                         @RequestParam("userStatus") Integer userStatus,
                                         @RequestParam("oldUserStatus") Integer oldUserStatus) {
        ChatGroup chatGroup = chatGroupService.getById(groupId);
        if (chatGroup == null) {
            return Result.failure("群组不存在！");
        }

        if (chatGroup.getGroupType().intValue() == ImConfigConst.GROUP_TOPIC) {
            return Result.failure("话题无需操作！");
        }

        String username = AuthUtils.getCurrentUsername();
        User currentUser = userService.getByUsername(username);
        String currentUserId = currentUser.getUserId();

        LambdaQueryChainWrapper<ChatGroupUser> lambdaQuery = chatGroupUserService.lambdaQuery();
        lambdaQuery.eq(ChatGroupUser::getGroupId, groupId);
        lambdaQuery.eq(ChatGroupUser::getUserId, currentUserId);
        lambdaQuery.eq(ChatGroupUser::getAdminFlag, ImConfigConst.ADMIN_FLAG_TRUE);
        ChatGroupUser groupUser = lambdaQuery.one();
        if (groupUser == null) {
            return Result.failure("没有审核权限！");
        }

        boolean isSuccess;
        if (userStatus == ImConfigConst.GROUP_USER_STATUS_BAN) {
            LambdaUpdateChainWrapper<ChatGroupUser> lambdaUpdate = chatGroupUserService.lambdaUpdate();
            lambdaUpdate.eq(ChatGroupUser::getGroupId, groupId);
            lambdaUpdate.eq(ChatGroupUser::getUserId, userId);
            lambdaUpdate.eq(ChatGroupUser::getAdminFlag, ImConfigConst.ADMIN_FLAG_FALSE);
            lambdaUpdate.eq(ChatGroupUser::getStatus, oldUserStatus);
            isSuccess = lambdaUpdate.remove();
        } else {
            LambdaUpdateChainWrapper<ChatGroupUser> lambdaUpdate = chatGroupUserService.lambdaUpdate();
            lambdaUpdate.eq(ChatGroupUser::getGroupId, groupId);
            lambdaUpdate.eq(ChatGroupUser::getUserId, userId);
            lambdaUpdate.eq(ChatGroupUser::getAdminFlag, ImConfigConst.ADMIN_FLAG_FALSE);
            lambdaUpdate.eq(ChatGroupUser::getStatus, oldUserStatus);
            lambdaUpdate.set(ChatGroupUser::getStatus, userStatus);
            if (userStatus == ImConfigConst.GROUP_USER_STATUS_PASS) {
                lambdaUpdate.set(ChatGroupUser::getVerifyUserId, currentUserId);
            }
            isSuccess = lambdaUpdate.update();
        }
        if (isSuccess && userStatus == ImConfigConst.GROUP_USER_STATUS_PASS) {
            Tio.bindGroup(tioWebsocketStarter.getServerTioConfig(), String.valueOf(userId), String.valueOf(groupId));
        } else if (isSuccess && userStatus.intValue() == ImConfigConst.GROUP_USER_STATUS_BAN &&
                (oldUserStatus.intValue() == ImConfigConst.GROUP_USER_STATUS_PASS ||
                        oldUserStatus.intValue() == ImConfigConst.GROUP_USER_STATUS_SILENCE)) {
            Tio.unbindGroup(tioWebsocketStarter.getServerTioConfig(), String.valueOf(userId), String.valueOf(groupId));
        }

        if (isSuccess) {
            return Result.success();
        } else {
            return Result.failure("修改失败！");
        }
    }

    /**
     * 设置群组管理员
     * <p>
     * adminFlag = true 是管理员
     * adminFlag = false 不是管理员
     */
    @GetMapping("/changeAdmin")
    //@PreAuthorize("@auth.permission('plugin:chat:group:update')")
    public Result changeAdmin(@RequestParam("groupId") Integer groupId,
                                    @RequestParam("userId") Integer userId,
                                    @RequestParam("adminFlag") Boolean adminFlag) {
        ChatGroup chatGroup = chatGroupService.getById(groupId);
        if (chatGroup == null) {
            return Result.failure("群组不存在！");
        }

        if (chatGroup.getGroupType().intValue() == ImConfigConst.GROUP_TOPIC) {
            return Result.failure("话题无需操作！");
        }

        String username = AuthUtils.getCurrentUsername();
        User currentUser = userService.getByUsername(username);
        String currentUserId = currentUser.getUserId();

        if (!chatGroup.getGroupAdminId().equals(currentUserId)) {
            return Result.failure("群主才能设置管理员！");
        }

        LambdaUpdateChainWrapper<ChatGroupUser> lambdaUpdate = chatGroupUserService.lambdaUpdate();
        lambdaUpdate.eq(ChatGroupUser::getGroupId, groupId);
        lambdaUpdate.eq(ChatGroupUser::getUserId, userId);
        lambdaUpdate.set(ChatGroupUser::getAdminFlag, adminFlag);

        lambdaUpdate.update();
        return Result.success();
    }

    /**
     * 退群
     */
    @GetMapping("/quitGroup")
    //@PreAuthorize("@auth.permission('plugin:chat:group:quit')")
    public Result quitGroup(@RequestParam("id") Integer id) {
        ChatGroup chatGroup = chatGroupService.getById(id);
        if (chatGroup == null) {
            return Result.failure("群组不存在！");
        }

        if (chatGroup.getGroupType().intValue() == ImConfigConst.GROUP_TOPIC) {
            return Result.failure("话题无需操作！");
        }

        String username = AuthUtils.getCurrentUsername();
        User currentUser = userService.getByUsername(username);
        String userId = currentUser.getUserId();


        if (chatGroup.getGroupAdminId().equals(userId)) {
            //转让群
            LambdaQueryChainWrapper<ChatGroupUser> wrapper = chatGroupUserService.lambdaQuery();
            wrapper.ne(ChatGroupUser::getUserId, userId);
            wrapper.last("order by admin_flag desc, create_time asc limit 1");
            ChatGroupUser one = wrapper.one();

            if (one == null) {
                //除了群主没别人，直接删除
                chatGroupService.removeById(id);
            } else {
                LambdaUpdateChainWrapper<ChatGroup> groupUpdate = chatGroupService.lambdaUpdate();
                groupUpdate.eq(ChatGroup::getId, id);
                groupUpdate.set(ChatGroup::getGroupAdminId, one.getUserId());
                groupUpdate.update();
                LambdaUpdateChainWrapper<ChatGroupUser> groupUserUpdate = chatGroupUserService.lambdaUpdate();
                groupUserUpdate.eq(ChatGroupUser::getId, one.getId());
                groupUserUpdate.set(ChatGroupUser::getAdminFlag, ImConfigConst.ADMIN_FLAG_TRUE);
                groupUserUpdate.update();
            }
        }

        LambdaUpdateChainWrapper<ChatGroupUser> lambdaUpdate = chatGroupUserService.lambdaUpdate();
        lambdaUpdate.eq(ChatGroupUser::getGroupId, id);
        lambdaUpdate.eq(ChatGroupUser::getUserId, userId);
        boolean isSuccess = lambdaUpdate.remove();
        if (isSuccess) {
            Tio.unbindGroup(tioWebsocketStarter.getServerTioConfig(), String.valueOf(userId), String.valueOf(id));
        }
        return Result.success();
    }

    /**
     * 群管理员查询群用户
     */
    @GetMapping("/getGroupUserByStatus")
    //@PreAuthorize("@auth.permission('plugin:chat:group:query')")
    public Result<Page> getGroupUserByStatus(@RequestParam(value = "groupId", required = false) Integer groupId,
                                                   @RequestParam(value = "userStatus", required = false) Integer userStatus,
                                                   @RequestParam(value = "current", defaultValue = "1") Long current,
                                                   @RequestParam(value = "size", defaultValue = "20") Long size) {
        String username = AuthUtils.getCurrentUsername();
        User currentUser = userService.getByUsername(username);
        String userId = currentUser.getUserId();

        Page<ChatGroupUser> page = new Page<>();
        page.setCurrent(current);
        page.setSize(size);
        LambdaQueryChainWrapper<ChatGroupUser> lambdaQuery = chatGroupUserService.lambdaQuery();
        if (groupId != null) {
            ChatGroup chatGroup = chatGroupService.getById(groupId);
            if (chatGroup == null) {
                return Result.failure("群组不存在！");
            }

            if (chatGroup.getGroupType().intValue() == ImConfigConst.GROUP_TOPIC) {
                return Result.failure("话题没有用户！");
            }

            LambdaQueryChainWrapper<ChatGroupUser> groupLambdaQuery = chatGroupUserService.lambdaQuery();
            groupLambdaQuery.eq(ChatGroupUser::getGroupId, groupId);
            groupLambdaQuery.eq(ChatGroupUser::getUserId, userId);
            groupLambdaQuery.eq(ChatGroupUser::getAdminFlag, ImConfigConst.ADMIN_FLAG_TRUE);
            ChatGroupUser groupUser = groupLambdaQuery.one();
            if (groupUser == null) {
                return Result.failure("没有审核权限！");
            }
            lambdaQuery.eq(ChatGroupUser::getGroupId, groupId);
        } else {
            LambdaQueryChainWrapper<ChatGroupUser> userLambdaQuery = chatGroupUserService.lambdaQuery();
            userLambdaQuery.eq(ChatGroupUser::getUserId, userId);
            userLambdaQuery.eq(ChatGroupUser::getAdminFlag, ImConfigConst.ADMIN_FLAG_TRUE);
            List<ChatGroupUser> groupUsers = userLambdaQuery.list();
            if (CollectionUtils.isEmpty(groupUsers)) {
                // 该用户没有管理任何群
                return Result.success();
            } else {
                List<Integer> groupIds = groupUsers.stream().map(ChatGroupUser::getGroupId).collect(Collectors.toList());
                lambdaQuery.in(ChatGroupUser::getGroupId, groupIds);
            }
        }

        if (userStatus != null) {
            lambdaQuery.eq(ChatGroupUser::getStatus, userStatus);
        }

        lambdaQuery.orderByDesc(ChatGroupUser::getGmtCreated).page(page);

        List<GroupUserVO> groupUserVOList = new ArrayList<>(page.getRecords().size());
        List<ChatGroupUser> records = page.getRecords();
        Map<Integer, List<ChatGroupUser>> map = records.stream().collect(Collectors.groupingBy(ChatGroupUser::getGroupId));
        List<ChatGroup> groups = chatGroupService.lambdaQuery().select(ChatGroup::getId, ChatGroup::getGroupName).in(ChatGroup::getId, map.keySet()).list();
        Map<Integer, String> collect = groups.stream().collect(Collectors.toMap(ChatGroup::getId, ChatGroup::getGroupName));
        map.forEach((key, value) -> {
            String groupName = collect.get(key);
            value.forEach(g -> {
                GroupUserVO groupUserVO = new GroupUserVO();
                BeanUtils.copyProperties(g, groupUserVO);
                groupUserVO.setGroupName(groupName);
                User user = userService.getById(groupUserVO.getUserId());
                if (user != null) {
                    groupUserVO.setUsername(user.getUsername());
                    groupUserVO.setAvatar(user.getAvatar());
                }
                groupUserVOList.add(groupUserVO);
            });
        });

        Page<GroupUserVO> result = new Page<>();
        result.setRecords(groupUserVOList);
        result.setTotal(page.getTotal());
        result.setCurrent(page.getCurrent());
        result.setSize(page.getSize());
        return Result.success(result);
    }

    /**
     * 群用户查询群用户
     */
    @GetMapping("/getGroupUser")
    //@PreAuthorize("@auth.permission('plugin:chat:group:query')")
    public Result<Page> getGroupUser(@RequestParam("groupId") Integer groupId,
                                           @RequestParam(value = "current", defaultValue = "1") Long current,
                                           @RequestParam(value = "size", defaultValue = "20") Long size) {
        ChatGroup chatGroup = chatGroupService.getById(groupId);
        if (chatGroup == null) {
            return Result.failure("群组不存在！");
        }

        if (chatGroup.getGroupType().intValue() == ImConfigConst.GROUP_TOPIC) {
            return Result.failure("话题没有用户！");
        }

        String username = AuthUtils.getCurrentUsername();
        User currentUser = userService.getByUsername(username);
        String userId = currentUser.getUserId();

        LambdaQueryChainWrapper<ChatGroupUser> wrapper = chatGroupUserService.lambdaQuery();
        wrapper.eq(ChatGroupUser::getUserId, userId);
        wrapper.eq(ChatGroupUser::getGroupId, groupId);
        wrapper.in(ChatGroupUser::getStatus, ImConfigConst.GROUP_USER_STATUS_PASS, ImConfigConst.GROUP_USER_STATUS_SILENCE);
        Integer count = wrapper.count();
        if (count < 1) {
            return Result.failure("未加群！");
        }

        Page<ChatGroupUser> page = new Page<>();
        page.setCurrent(current);
        page.setSize(size);
        LambdaQueryChainWrapper<ChatGroupUser> lambdaQuery = chatGroupUserService.lambdaQuery();
        lambdaQuery.eq(ChatGroupUser::getGroupId, groupId);
        lambdaQuery.in(ChatGroupUser::getStatus, ImConfigConst.GROUP_USER_STATUS_PASS, ImConfigConst.GROUP_USER_STATUS_SILENCE);
        lambdaQuery.orderByAsc(ChatGroupUser::getGmtCreated).page(page);

        List<GroupUserVO> groupUserVOList = new ArrayList<>(page.getRecords().size());
        List<ChatGroupUser> records = page.getRecords();
        records.forEach(g -> {
            GroupUserVO groupUserVO = new GroupUserVO();
            BeanUtils.copyProperties(g, groupUserVO);
            groupUserVO.setGroupName(chatGroup.getGroupName());
            User user = userService.getById(groupUserVO.getUserId());
            if (user != null) {
                groupUserVO.setUsername(user.getUsername());
                groupUserVO.setAvatar(user.getAvatar());
            }
            groupUserVOList.add(groupUserVO);
        });

        Page<GroupUserVO> result = new Page<>();
        result.setRecords(groupUserVOList);
        result.setTotal(page.getTotal());
        result.setCurrent(page.getCurrent());
        result.setSize(page.getSize());
        return Result.success(result);
    }
}

